#import "MopExtWechatPlugin.h"
#import <FinAppletWXExt/FinAppletWXExt.h>

@interface MopExtWechatPlugin()<FATWXExtButtonOpenTypeDelegate>

@property (nonatomic, strong) FlutterMethodChannel *channel;

@end

NSString *const successKey = @"success";

@implementation MopExtWechatPlugin

+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
    FlutterMethodChannel* channel = [FlutterMethodChannel
                                     methodChannelWithName:@"mop_ext_wechat"
                                     binaryMessenger:[registrar messenger]];
    MopExtWechatPlugin* instance = [[MopExtWechatPlugin alloc] init];
    instance.channel = channel;
    [registrar addMethodCallDelegate:instance channel:channel];
    
    // 设置代理
    [FATDelegateClientHelper sharedHelper].buttonOpenTypeDelegate = instance;
    
}

- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
    if ([call.method isEqualToString:@"registerComponent"]) {
        
        [self handleRegisterComponent:call result:result];
    }
}

#pragma mark - handle registerComponent method call

- (void)handleRegisterComponent:(FlutterMethodCall*)call result:(FlutterResult)result {
    NSDictionary *params = call.arguments;
    if (![params isKindOfClass:NSDictionary.class]) {
        result([self getResultDictWithErrMsg:@"params type error"]);
        return;
    }
    NSString *wxAppId = params[@"wxAppId"];
    NSString *universalLink = params[@"universalLink"];
    
    BOOL success = [FATWXExtComponent registerComponent:wxAppId universalLink:universalLink];
    
    if (success) {
        result([self getResultDictWithSuccess]);
    } else {
        result([self getResultDictWithErrMsg:@"register component fail, Please check if the parameters are correct"]);
    }
    
}



#pragma mark - get errorMessage

- (NSDictionary *)getResultDictWithErrMsg:(NSString *)errMsg {
    NSDictionary *dict = @{
        @"retMsg": errMsg,
        @"success": @(NO)
    };
    return dict;
}

- (NSDictionary *)getResultDictWithSuccess {
    NSDictionary *dict = @{
        @"retMsg": @"success",
        @"success": @(YES)
    };
    return dict;
}

#pragma mark - FATAppletButtonOpenTypeDelegate

- (BOOL)respondsToSelector:(SEL)aSelector {
    /**
     case 'forwardApplet':
     case 'getUserInfo':
     case 'getUserProfile':
     case 'contact':
     case 'getPhoneNumber':
     case 'launchApp':
     case 'feedback':
     case 'chooseAvatar':
     */
    NSString *methodName;
    if (aSelector == @selector(forwardAppletWithInfo:completion:)) {
        methodName = @"forwardApplet";
    } else if (aSelector == @selector(getUserInfoWithAppletInfo:bindGetUserInfo:)) {
        methodName = @"getUserInfo";
    } else if (aSelector == @selector(getUserProfileWithAppletInfo:bindGetUserProfile:)) {
        methodName = @"getUserProfile";
    } else if (aSelector == @selector(contactWithAppletInfo:sessionFrom:sendMessageTitle:sendMessagePath:sendMessageImg:showMessageCard:)) {
        methodName = @"contact";
    } else if (aSelector == @selector(getPhoneNumberWithAppletInfo:bindGetPhoneNumber:)) {
        methodName = @"getPhoneNumber";
    } else if (aSelector == @selector(launchAppWithAppletInfo:appParameter:bindError:bindLaunchApp:)) {
        methodName = @"launchApp";
    } else if (aSelector == @selector(feedbackWithAppletInfo:)) {
        methodName = @"feedback";
    } else if (aSelector == @selector(chooseAvatarWithAppletInfo:bindChooseAvatar:)) {
        methodName = @"chooseAvatar";
    }
    if (methodName) {
        __block BOOL hasMethod = NO;
        [self.channel invokeMethod:@"hasMethod" arguments:@{@"methodName": methodName} result:^(id  _Nullable result) {
            if ([result isKindOfClass:NSNumber.class]) {
                hasMethod = [result boolValue];
            }
            CFRunLoopStop(CFRunLoopGetMain());
        }];
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            CFRunLoopStop(CFRunLoopGetMain());
        });
        CFRunLoopRun();
        return hasMethod;
    }
    return [super respondsToSelector:aSelector];
    
}

- (BOOL)forwardAppletWithInfo:(NSDictionary *)contentInfo completion:(void (^)(FATExtensionCode, NSDictionary *))completion {
    __block BOOL flag = NO;
    NSDictionary *params = @{
        @"appletInfo": contentInfo
    };
    NSString *jsonString = [self dictToJsonString:params];
    [self.channel invokeMethod:@"forwardApplet" arguments:jsonString result:^(id result) {
        flag = [self getHandlerHasImpl:result];
        if (flag) {
            NSDictionary *data = [self getHandlerResultData:result];
            id resultObj = data[@"result"];
            BOOL forwardAppletResult = NO;
            
            if ([resultObj respondsToSelector:@selector(boolValue)]) {
                forwardAppletResult = [resultObj boolValue];
            }
            if (completion) {
                if (forwardAppletResult) {
                    completion(FATExtensionCodeSuccess, @{});
                } else {
                    completion(FATExtensionCodeFailure, @{});
                }
            }
        }
        
        CFRunLoopStop(CFRunLoopGetMain());
        
    }];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        CFRunLoopStop(CFRunLoopGetMain());
    });
    CFRunLoopRun();
    return flag;
}

- (BOOL)getUserInfoWithAppletInfo:(FATAppletInfo *)appletInfo bindGetUserInfo:(void (^)(NSDictionary *))bindGetUserInfo {
    __block BOOL flag = NO;
    NSDictionary *params = @{
        @"appletInfo": [self appletInfoToDict:appletInfo]
    };
    NSString *jsonString = [self dictToJsonString:params];
    
    [self.channel invokeMethod:@"getUserInfo" arguments:jsonString result:^(id result) {
        
        flag = [self getHandlerHasImpl:result];
        if (flag) {
            NSDictionary *data = [self getHandlerResultData:result];
            if (bindGetUserInfo) {
                bindGetUserInfo(data);
            }
        }
        CFRunLoopStop(CFRunLoopGetMain());
    }];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        CFRunLoopStop(CFRunLoopGetMain());
    });
    CFRunLoopRun();
    return flag;
}

- (BOOL)getUserProfileWithAppletInfo:(FATAppletInfo *)appletInfo bindGetUserProfile:(void (^)(NSDictionary *))bindGetUserProfile {
    __block BOOL flag = NO;
    
    NSDictionary *params = @{
        @"appletInfo": [self appletInfoToDict:appletInfo]
    };
    NSString *jsonString = [self dictToJsonString:params];
    
    [self.channel invokeMethod:@"getUserProfile" arguments:jsonString result:^(id result) {
        flag = [self getHandlerHasImpl:result];
        if (flag) {
            NSDictionary *data = [self getHandlerResultData:result];
            if (bindGetUserProfile) {
                bindGetUserProfile(data);
            }
        }
        CFRunLoopStop(CFRunLoopGetMain());
    }];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        CFRunLoopStop(CFRunLoopGetMain());
    });
    CFRunLoopRun();
    return flag;
}

- (BOOL)contactWithAppletInfo:(FATAppletInfo *)appletInfo sessionFrom:(NSString *)sessionFrom sendMessageTitle:(NSString *)sendMessageTitle sendMessagePath:(NSString *)sendMessagePath sendMessageImg:(NSString *)sendMessageImg showMessageCard:(BOOL)showMessageCard {
    __block BOOL flag = NO;
    NSDictionary *params = @{
        @"appletInfo": [self appletInfoToDict:appletInfo],
        @"sessionFrom": sessionFrom ?: @"",
        @"sendMessageTitle": sendMessageTitle ?: @"",
        @"sendMessagePath": sendMessagePath ?: @"",
        @"sendMessageImg": sendMessageImg ?: @"",
        @"showMessageCard": @(showMessageCard)
    };
    NSString *jsonString = [self dictToJsonString:params];
    [self.channel invokeMethod:@"contact" arguments:jsonString result:^(id  _Nullable result) {
        flag = [self getHandlerHasImpl:result];
        CFRunLoopStop(CFRunLoopGetMain());
    }];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        CFRunLoopStop(CFRunLoopGetMain());
    });
    CFRunLoopRun();
    return flag;
}

- (BOOL)getPhoneNumberWithAppletInfo:(FATAppletInfo *)appletInfo bindGetPhoneNumber:(void (^)(NSDictionary *))bindGetPhoneNumber {
    __block BOOL flag = NO;
    
    NSDictionary *params = @{
        @"appletInfo": [self appletInfoToDict:appletInfo]
    };
    NSString *jsonString = [self dictToJsonString:params];
    
    [self.channel invokeMethod:@"getPhoneNumber" arguments:jsonString result:^(id result) {
        flag = [self getHandlerHasImpl:result];
        if (flag) {
            NSDictionary *data = [self getHandlerResultData:result];
            if (bindGetPhoneNumber) {
                bindGetPhoneNumber(data);
            }
        }
        CFRunLoopStop(CFRunLoopGetMain());
    }];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        CFRunLoopStop(CFRunLoopGetMain());
    });
    CFRunLoopRun();
    return flag;
}

- (BOOL)launchAppWithAppletInfo:(FATAppletInfo *)appletInfo appParameter:(NSString *)appParameter bindError:(void (^)(NSDictionary *))bindError bindLaunchApp:(void (^)(NSDictionary *))bindLaunchApp {
    __block BOOL flag = NO;
    NSDictionary *params = @{
        @"appletInfo": [self appletInfoToDict:appletInfo],
        @"appParameter": appParameter ?: @""
    };
    NSString *jsonString = [self dictToJsonString:params];
    [self.channel invokeMethod:@"launchApp" arguments:jsonString result:^(id result) {
        flag = [self getHandlerHasImpl:result];
        NSDictionary *data = [self getHandlerResultData:result];
        if (flag) {
            if (bindLaunchApp) {
                bindLaunchApp(data);
            }
            
        } else {
            if (bindError) {
                bindError(data);
            }
        }
        CFRunLoopStop(CFRunLoopGetMain());
    }];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        CFRunLoopStop(CFRunLoopGetMain());
    });
    CFRunLoopRun();
    return flag;
}

- (BOOL)feedbackWithAppletInfo:(FATAppletInfo *)appletInfo {
    __block BOOL flag = NO;
    
    NSDictionary *params = @{
        @"appletInfo": [self appletInfoToDict:appletInfo]
    };
    NSString *jsonString = [self dictToJsonString:params];
    
    [self.channel invokeMethod:@"feedback" arguments:jsonString result:^(id  _Nullable result) {
        flag = [self getHandlerHasImpl:result];
        CFRunLoopStop(CFRunLoopGetMain());
    }];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        CFRunLoopStop(CFRunLoopGetMain());
    });
    CFRunLoopRun();
    return flag;
}

- (BOOL)chooseAvatarWithAppletInfo:(FATAppletInfo *)appletInfo bindChooseAvatar:(void (^)(NSDictionary *))bindChooseAvatar {
    __block BOOL flag = NO;
    
    NSDictionary *dict = @{
        @"appletInfo": [self appletInfoToDict:appletInfo]
    };
    NSString *jsonString = [self dictToJsonString:dict];
    
    [self.channel invokeMethod:@"chooseAvatar" arguments:jsonString result:^(id result) {
        flag = [self getHandlerHasImpl:result];
        if (flag) {
            NSDictionary *data = [self getHandlerResultData:result];
            if (bindChooseAvatar) {
                bindChooseAvatar(data);
            }
        }
        CFRunLoopStop(CFRunLoopGetMain());
    }];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        CFRunLoopStop(CFRunLoopGetMain());
    });
    CFRunLoopRun();
    return flag;
}

#pragma mark - Helper Methods


/// flutter 端是否有实现对应的函数
///
/// - Parameter dict: flutter 返回的总数据
///
- (BOOL)getHandlerHasImpl:(id)dict {
    if ([dict isKindOfClass:NSDictionary.class]) {
        NSNumber *handler = dict[successKey];
        if ([handler respondsToSelector:@selector(boolValue)]) {
            return [handler boolValue];
        }
    }
    return NO;
}

/// flutter端函数实现返回的数据
///
/// - Parameter dict: flutter 返回的总数据
///
- (NSDictionary *)getHandlerResultData:(id)dict {
    if ([dict isKindOfClass:NSDictionary.class]) {
        NSDictionary *data = dict[@"data"];
        if ([data isKindOfClass:NSDictionary.class]) {
            return data;
        }
    }
    return nil;
}

- (NSDictionary *)appletInfoToDict:(FATAppletInfo *)appletInfo {
    NSDictionary *dict = [appletInfo convertToDictionary];
    return dict ?: @{};
}


- (NSString *)dictToJsonString:(NSDictionary *)dict {
    NSError *error;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:&error];

    NSString *jsonString = @"";
    if (jsonData) {
        jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    }
    return jsonString;
}

@end
